{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RecursiveDo #-}

module Main where

import GHCJS.DOM.WebGLRenderingContextBase
import GHCJS.DOM.Types hiding (Text)
import GHCJS.Types
import GHCJS.DOM

import Shader
import Utils

import GHCJS.DOM.Window (requestAnimationFrame)
import GHCJS.DOM.RequestAnimationFrameCallback (newRequestAnimationFrameCallback)

import Data.IORef
import Data.StateVar
import Data.Time.Clock
import Control.Monad
import Control.Lens
import Linear
main :: IO ()
main = runWebGUI $ \win -> do
  enableInspector win
  Just doc <- webViewGetDomDocument win
  gl <- initGL doc
  program <- initShader gl
  let n = 3
      vertics = [0.0, 0.5, -0.5, -0.5, 0.5, -0.5]

  vertVal <- doubles2Float32Array vertics
  vbo <- createBuffer gl
  bindBuffer gl ARRAY_BUFFER vbo
  bufferData gl ARRAY_BUFFER (Just . ArrayBuffer . jsval $ vertVal ) STATIC_DRAW

  aPosition <- fromIntegral <$> getAttribLocation gl program "a_Position"
  vertexAttribPointer gl aPosition 2 FLOAT False 0 0
  enableVertexAttribArray gl aPosition

  cAngle <- newIORef 0.0
  nowTime <- newIORef =<< getCurrentTime
  xformMatrix <- getUniformLocation gl program "u_ModelMatrix"
  let xMove :: M44 Double = identity & translation .~ V3 0.35 0.0 0.0
      draw currentRadian = do
        let mat = m33_to_m44 (fromQuaternion (axisAngle (V3 0 0 1) currentRadian))
              !*! xMove

        m <- matReady mat
        uniformMatrix4fv gl xformMatrix False (Just . Float32Array . jsval $ m)
        clear gl COLOR_BUFFER_BIT
        drawArrays gl TRIANGLE_STRIP 0 n
      step = 45.0
      animate = do
        ang <- get cAngle
        now <- getCurrentTime
        lastTime <- get nowTime
        nowTime $= now
        let afterStep = ang + realToFrac (diffUTCTime now lastTime) * step
        cAngle $= afterStep
        pure afterStep
      go = do
        rec cb <- newRequestAnimationFrameCallback $ \_ -> do
              currentAngle <- animate
              draw (angle2radian currentAngle)
              void next
            let next = requestAnimationFrame win (Just cb)
        void next

  clearColor gl 0.0 0.0 0.0 1.0
  go
